﻿using System.Collections.Generic;
using Notoric.Commanding.CommandBase;

namespace Notoric.Commanding
{
    /// <summary>
    /// Implements a simple undoable macro command that executes the commands from the <see cref="Commands"/>
    /// list in the order given by this list.<br/>
    /// The subcommands can only be the <see cref="UndoableCommandBase"/> instances.
    /// </summary>
    /// <seealso cref="SingleUseMacroCommand"/>
    /// <seealso cref="UndoableCommandBase"/>
    public class UndoableMacroCommand : UndoableCommandBase
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="UndoableMacroCommand"/> isntance.
        /// </summary>
        /// <param name="undoStack">Reference to the undo stack</param>
        /// <param name="redoStack">Reference to the redo stack</param>
        public UndoableMacroCommand(CommandStack undoStack, CommandStack redoStack)
            : base(undoStack, redoStack)
        {
        }

        #endregion

        #region Inherited UndoableCommandBase Abstract Members

        /// <summary>
        /// Executes all the commands in the <see cref="Commands"/> list.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null"/>.
        /// The parameter value is passed to all the executed subcommands.
        /// </param>
        protected override void CommandOperation(object parameter)
        {
            foreach (UndoableCommandBase cmd in commands)
                cmd.ExecuteCommand(parameter);
        }

        /// <summary>
        /// Redoes all the commands in the <see cref="Commands"/> list.
        /// </summary>
        protected override void RedoOperation()
        {
            foreach (UndoableCommandBase cmd in commands)
                cmd.RedoCommand();
        }

        /// <summary>
        /// Undoes all the commands in the <see cref="Commands"/> list.
        /// </summary>
        protected override void UndoOperation()
        {
            for (int i = commands.Count - 1; i >= 0; --i)
                commands[i].UndoCommand();
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the list of commands that are part of this macro.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="List{T}"/> of <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// Collection of the commands that are part of this macro. The commands are executed in the same
        /// order as they are in the list.
        /// </para>
        /// </value>
        public List<UndoableCommandBase> Commands
        {
            get { return commands; }
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the collection of the commands that are part of this macro.
        /// </summary>
        private List<UndoableCommandBase> commands = new List<UndoableCommandBase>();

        #endregion
    }
}
